using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[RequireComponent(typeof(ScrollRect))]
public class UScrollPage : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler, IEventSystemHandler
{
	public int CurrentIndex
	{
		get
		{
			if (this.content == null)
			{
				UnityEngine.Debug.LogError("UScrollPage.CurrentIndex : Content is null.");
				return -1;
			}
			return this.GetClosestIndex();
		}
		set
		{
			if (value < 0 || value >= this.pages.Count)
			{
				return;
			}
			Vector3 localPosition = this.pages[value].localPosition;
			localPosition.x *= -1f;
			this.content.localPosition = localPosition;
			this.destination = this.content.localPosition;
		}
	}

	public int PageCount
	{
		get
		{
			return this.pages.Count;
		}
	}

	private void Awake()
	{
		this.Initialize();
	}

	private void Start()
	{
		this.InvalidatePages();
	}

	private void OnEnable()
	{
		this.InvalidatePages();
		this.scrollRect.onValueChanged.AddListener(new UnityAction<Vector2>(this.OnValueChanged));
	}

	private void OnDisable()
	{
		this.scrollRect.onValueChanged.RemoveListener(new UnityAction<Vector2>(this.OnValueChanged));
	}

	private void Update()
	{
		if (!this.dragging)
		{
			this.content.localPosition = Vector3.Lerp(this.content.localPosition, this.destination, this.transferSpeed * Time.deltaTime);
			if (Mathf.Approximately(0f, Vector3.Distance(this.content.localPosition, this.destination)))
			{
				this.content.localPosition = this.destination;
			}
		}
	}

	private void OnValueChanged(Vector2 v)
	{
		this.InvalidatePages();
	}

	public void AddPage(RectTransform page)
	{
		float x;
		if (this.pages.Count > 0)
		{
			RectTransform rectTransform = this.pages[this.pages.Count - 1];
			x = rectTransform.anchoredPosition.x + rectTransform.sizeDelta.x + (float)this.pageGap;
		}
		else
		{
			x = this.scrollRectTF.sizeDelta.x * 0.5f;
		}
		page.SetParent(this.content, false);
		page.pivot = new Vector2(0.5f, 0.5f);
		page.anchorMin = new Vector2(0f, 0.5f);
		page.anchorMax = new Vector2(0f, 0.5f);
		page.anchoredPosition = new Vector2(x, 0f);
		this.pages.Add(page);
		this.InvalidateContentSize();
		if (this.useIndicator)
		{
			this.BuildIndicator();
		}
		if (this.pages.Count == 1)
		{
			this.CurrentIndex = 0;
		}
	}

	public RectTransform RemovePage(int index)
	{
		if (index < 0 || index >= this.pages.Count)
		{
			UnityEngine.Debug.LogError("UScrollPage.RemovePage : Out of index");
			return null;
		}
		RectTransform rectTransform = this.pages[index];
		this.pages.RemoveAt(index);
		rectTransform.SetParent(null, false);
		this.ArrangePages();
		if (this.useIndicator)
		{
			this.BuildIndicator();
		}
		return rectTransform;
	}

	public void MoveTo(int index)
	{
		if (this.pages.Count == 0)
		{
			return;
		}
		if (Mathf.Approximately(this.content.localPosition.x, this.pages[index].localPosition.x))
		{
			return;
		}
		Vector3 localPosition = this.pages[index].localPosition;
		localPosition.x *= -1f;
		this.destination = localPosition;
	}

	public void MoveNext()
	{
		int num = this.CurrentIndex + 1;
		if (num >= this.pages.Count)
		{
			return;
		}
		this.CurrentIndex = num;
	}

	public void MovePrev()
	{
		int num = this.CurrentIndex - 1;
		if (num < 0)
		{
			return;
		}
		this.CurrentIndex = num;
	}

	public void OnBeginDrag(PointerEventData eventData)
	{
		this.dragging = true;
		this.beginDragIndex = this.CurrentIndex;
		this.downValue = this.content.localPosition.x;
		this.pressTime = Time.realtimeSinceStartup;
	}

	public void OnDrag(PointerEventData eventData)
	{
	}

	public void OnEndDrag(PointerEventData eventData)
	{
		this.dragging = false;
		if (this.beginDragIndex == this.CurrentIndex)
		{
			float num = Time.realtimeSinceStartup - this.pressTime;
			if (num < this.swipeTimeThreshold)
			{
				this.FastSwipe(num);
			}
			else
			{
				this.MoveTo(this.CurrentIndex);
			}
		}
		else
		{
			this.MoveTo(this.CurrentIndex);
		}
	}

	private void Initialize()
	{
		this.scrollRect = base.gameObject.GetComponent<ScrollRect>();
		this.scrollRectTF = (this.scrollRect.transform as RectTransform);
		if (this.indicatorSelected != null)
		{
			this.indicatorSize = this.indicatorSelected.textureRect.size;
		}
		if (this.scrollRect.content == null)
		{
			UnityEngine.Debug.LogError("UScrollPage.Start : Content is null.");
			return;
		}
		this.scrollRect.inertia = false;
		this.scrollRect.movementType = ScrollRect.MovementType.Unrestricted;
		this.content = this.scrollRect.content;
		this.content.pivot = new Vector2(0f, 0.5f);
		this.content.anchorMin = new Vector2(0.5f, 0.5f);
		this.content.anchorMax = new Vector2(0.5f, 0.5f);
		for (int i = 0; i < this.content.childCount; i++)
		{
			RectTransform component = this.content.GetChild(i).GetComponent<RectTransform>();
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.anchorMax = new Vector2(0f, 0.5f);
			this.pages.Add(component);
		}
		this.ArrangePages();
		if (this.useIndicator)
		{
			this.BuildIndicator();
		}
	}

	private void ArrangePages()
	{
		float num = this.scrollRectTF.sizeDelta.x * 0.5f;
		for (int i = 0; i < this.pages.Count; i++)
		{
			if (i > 0)
			{
				num += (float)this.pageGap;
			}
			this.pages[i].anchoredPosition = new Vector2(num, 0f);
			num += this.pages[i].sizeDelta.x;
		}
		this.InvalidateContentSize();
		this.CurrentIndex = this.GetClosestIndex();
	}

	private int GetClosestIndex()
	{
		int result = -1;
		float num = float.PositiveInfinity;
		for (int i = 0; i < this.pages.Count; i++)
		{
			Vector3 localPosition = this.content.localPosition;
			localPosition.x *= -1f;
			float num2 = Vector3.Distance(localPosition, this.pages[i].localPosition);
			if (num2 < num)
			{
				num = num2;
				result = i;
			}
		}
		return result;
	}

	private void FastSwipe(float movementSec)
	{
		float x = this.content.localPosition.x;
		float num = (x - this.downValue) / movementSec * Time.deltaTime;
		float num2 = Mathf.Abs(num);
		if (num2 > this.swipeMoveThreshold)
		{
			if (num < 0f)
			{
				this.MoveTo(Mathf.Min(this.pages.Count - 1, this.CurrentIndex + 1));
			}
			else
			{
				this.MoveTo(Mathf.Max(0, this.CurrentIndex - 1));
			}
		}
	}

	private List<int> GetVisiblePageIndices()
	{
		List<int> list = new List<int>();
		Rect worldRect = this.GetWorldRect(this.scrollRectTF);
		for (int i = 0; i < this.pages.Count; i++)
		{
			if (worldRect.Overlaps(this.GetWorldRect(this.pages[i])))
			{
				list.Add(i);
			}
		}
		return list;
	}

	private Rect GetWorldRect(RectTransform rt)
	{
		Vector3[] array = new Vector3[4];
		rt.GetWorldCorners(array);
		return new Rect(array[1].x, array[1].y, Vector3.Distance(array[1], array[2]), Vector3.Distance(array[0], array[1]));
	}

	private void InvalidateContentSize()
	{
		if (this.pages.Count > 0)
		{
			float num = this.scrollRectTF.sizeDelta.x * 0.5f;
			float x = this.pages[this.pages.Count - 1].anchoredPosition.x + num;
			this.content.sizeDelta = new Vector2(x, this.scrollRectTF.sizeDelta.y);
		}
		else
		{
			this.content.anchoredPosition = Vector2.zero;
			this.content.sizeDelta = this.scrollRectTF.sizeDelta;
			this.destination = this.content.localPosition;
		}
	}

	private void InvalidatePages()
	{
		List<int> visiblePageIndices = this.GetVisiblePageIndices();
		for (int i = 0; i < visiblePageIndices.Count; i++)
		{
			if (!this.visiblePages.Contains(visiblePageIndices[i]))
			{
				if (this.onAppearPage != null)
				{
					this.onAppearPage(visiblePageIndices[i], this.pages[visiblePageIndices[i]]);
				}
			}
		}
		for (int j = 0; j < this.visiblePages.Count; j++)
		{
			if (!visiblePageIndices.Contains(this.visiblePages[j]))
			{
				if (this.onDisappearPage != null)
				{
					this.onDisappearPage(this.visiblePages[j], this.pages[this.visiblePages[j]]);
				}
			}
		}
		this.visiblePages.Clear();
		this.visiblePages.AddRange(visiblePageIndices);
		this.UpdateIndicator();
	}

	private void BuildIndicator()
	{
		if (this.indicatorRoot == null)
		{
			this.indicatorRoot = this.CreateIndicatorToggleGroup();
			float num = this.scrollRectTF.sizeDelta.y * 0.5f;
			if (this.indicatorPosition == UScrollPage.INDICATOR_POSITION.TOP)
			{
				num += this.indicatorFromScroll;
			}
			else
			{
				num *= -1f;
				num -= this.indicatorFromScroll;
			}
			num += this.scrollRectTF.anchoredPosition.y;
			(this.indicatorRoot.transform as RectTransform).anchoredPosition = new Vector2(0f, num);
		}
		while (this.indicators.Count != this.pages.Count)
		{
			if (this.pages.Count > this.indicators.Count)
			{
				this.indicators.Add(this.CreateIndicatorToggle(this.indicatorRoot));
			}
			else if (this.pages.Count < this.indicators.Count)
			{
				UnityEngine.Object.Destroy(this.indicators[this.indicators.Count - 1].gameObject);
				this.indicators.RemoveAt(this.indicators.Count - 1);
			}
		}
		float num2 = (float)this.indicators.Count * this.indicatorSize.x * -0.5f;
		for (int i = 0; i < this.indicators.Count; i++)
		{
			RectTransform rectTransform = this.indicators[i].transform as RectTransform;
			rectTransform.anchoredPosition = new Vector2(num2 + (float)i * this.indicatorSize.x, 0f);
		}
	}

	private void UpdateIndicator()
	{
		int currentIndex = this.CurrentIndex;
		for (int i = 0; i < this.indicators.Count; i++)
		{
			this.indicators[i].isOn = (i == currentIndex);
		}
	}

	private ToggleGroup CreateIndicatorToggleGroup()
	{
		GameObject gameObject = new GameObject("Indicators");
		RectTransform rectTransform = gameObject.AddComponent<RectTransform>();
		rectTransform.SetParent(this.scrollRectTF.parent, false);
		rectTransform.anchoredPosition = Vector2.zero;
		return gameObject.AddComponent<ToggleGroup>();
	}

	private Toggle CreateIndicatorToggle(ToggleGroup tgg)
	{
		GameObject gameObject = new GameObject("Indicator");
		RectTransform rectTransform = gameObject.AddComponent<RectTransform>();
		rectTransform.SetParent(tgg.transform, false);
		rectTransform.anchoredPosition = Vector2.zero;
		rectTransform.sizeDelta = this.indicatorSize;
		Image image = this.CreateToggleImage("Background", this.indicatorUnselected, rectTransform);
		Image graphic = this.CreateToggleImage("Mark", this.indicatorSelected, image.transform as RectTransform);
		Toggle toggle = gameObject.AddComponent<Toggle>();
		toggle.interactable = false;
		toggle.transition = Selectable.Transition.None;
		toggle.graphic = graphic;
		toggle.group = tgg;
		return toggle;
	}

	private Image CreateToggleImage(string name, Sprite sprite, RectTransform parent)
	{
		GameObject gameObject = new GameObject(name);
		RectTransform rectTransform = gameObject.AddComponent<RectTransform>();
		rectTransform.SetParent(parent, false);
		rectTransform.anchoredPosition = Vector2.zero;
		rectTransform.sizeDelta = sprite.bounds.size;
		gameObject.AddComponent<CanvasRenderer>();
		Image image = gameObject.AddComponent<Image>();
		image.sprite = sprite;
		image.preserveAspect = true;
		image.SetNativeSize();
		return image;
	}

	[Tooltip("Gap between pages")]
	public int pageGap;

	[Tooltip("Swipe speed")]
	public float transferSpeed = 10f;

	[Tooltip("Movement per second for fast swipe")]
	public float swipeMoveThreshold = 5f;

	[Tooltip("Duration sec for fast swipe")]
	public float swipeTimeThreshold = 0.3f;

	[Tooltip("Use indicator")]
	public bool useIndicator;

	[Tooltip("Gap between indicators")]
	public float indicatorGap;

	[Tooltip("Distance between indicators and scroll")]
	public float indicatorFromScroll = 10f;

	[Tooltip("Indicator Position")]
	public UScrollPage.INDICATOR_POSITION indicatorPosition = UScrollPage.INDICATOR_POSITION.BOTTOM;

	[Tooltip("Selected indicator")]
	public Sprite indicatorSelected;

	[Tooltip("Unselected indicator")]
	public Sprite indicatorUnselected;

	public Action<int, RectTransform> onAppearPage;

	public Action<int, RectTransform> onDisappearPage;

	private bool dragging;

	private float downValue;

	private float pressTime;

	private int beginDragIndex;

	private Vector3 destination;

	private Vector2 indicatorSize;

	private ScrollRect scrollRect;

	private RectTransform content;

	private ToggleGroup indicatorRoot;

	private RectTransform scrollRectTF;

	private List<int> visiblePages = new List<int>();

	private List<RectTransform> pages = new List<RectTransform>();

	private List<Toggle> indicators = new List<Toggle>();

	public enum INDICATOR_POSITION
	{
		TOP,
		BOTTOM
	}
}
